package bayes;

import java.util.Arrays;
import java.util.Iterator;
import java.util.Vector;

import bayes.nodeTypes.Variable;

public class Node {

	private Variable 		_variable;
	private String			_name;
	private	Node			_parent;
	private	Vector<Node>	_children;
	private double[][] 		_probabilities;
	private int 			_domainSize;

	public Node(Variable variable, String name, Node parent, int domainSize) {
		this._variable		= variable;
		this._name 			= name;
		this._parent 		= parent;
		this._children		= new Vector<Node>();
		this._probabilities = new double[parent.getDomainSize()][domainSize];
		this._domainSize 	= domainSize;

	}

	// constructor for root node:
	public Node(Variable variable, String name, int domainSize) {
		this._variable		= variable;
		this._name 			= name;
		this._parent		= null;
		this._children		= new Vector<Node>();
		this._probabilities = new double[1][domainSize];
		this._domainSize 	= domainSize;
	}

	private int getDomainSize() {
		return _domainSize;
	}

	public double getProbability(int parentDomainValue, int myDomainValue){
		return this._probabilities[parentDomainValue][myDomainValue];
	}
	
	public double getProbability(int domainValue) {
		double ans = 0;
		
		for (int i = 0; i < this._probabilities.length; i++) {
			ans += this._probabilities[i][domainValue];
		}
		if (ans > 1 )	System.err.println("are u crazy "+6/0);
		return ans;
	}
	
	public void setProbability(int parentDomainValue, int myDomainValue, double probability){
		this._probabilities[parentDomainValue][myDomainValue] = probability;
	}

	public void addChild(Node childNode){
		_children.addElement(childNode);
	}

	public void set_parent(Node _parent) {
		this._parent = _parent;
	}

	public Node get_parent() {
		return _parent;
	}

	@Override
	public String toString() {
		String ret = "\n----- Node: " + this._name + " ------\n";
		
		// printing parent:
		ret += "Parent name: ";
		if (hasParents())
			ret += this._parent._name;
		else
			ret += "No parent";
		
		// printing chilren:
		ret += "\nChildren   : ";
		for (Iterator<Node> iterator = this._children.iterator(); iterator.hasNext();) {
			Node child = iterator.next();
			ret += child._name + ",  ";
		}
		ret += "\n";
		
		
		// printing probabilities table:
		String[] leftSize;
		if (hasParents()){
			leftSize = new String[this._parent.get_Variable().get_domainSize()];
			for (int i = 0; i < this._probabilities.length; i++) {
				//ret += this._parent.get_Variable().getDomainValName(i)+"  ";
				leftSize[i] = this._parent.get_Variable().getDomainValName(i);
			}
		} else{
			leftSize = new String[2];
			leftSize[0] = "TRUE";
			leftSize[1] = "FALSE";
		}
		
		// first row:
		ret += "      ";
		for (int i = 0; i < this._probabilities[0].length; i++) {
			ret += this._variable.getDomainValName(i)+"  ";
		}
		
		
		// table itself:
		for (int i = 0; i < this._probabilities.length; i++) {
			ret += "\n" + leftSize[i] + /*this._variable.getDomainValName(i)+*/" " + Arrays.toString(_probabilities[i]);
		}
		ret += "\n-------------------------\n";
		return ret;
	}

	public boolean hasParents() {
		return this._parent != null;
	}

	private Variable get_Variable() {
		return this._variable;
	}

	public int get_domainSize() {
		return _domainSize;
	}

	public Variable getVariable() {
		return this._variable;
	}

	public String get_name() {
		return this._name;
	}

	public int get_index() {
		return this._variable.get_id();
	}

	public int getNumberOfChildren() {
		return this._children.size();
	}

	public Node get_child(int i) {
		return this._children.elementAt(i);
	}
}
